package org.apache.ocean.main;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;

import org.apache.lucene.document.Document;
import org.apache.lucene.document.Fieldable;
import org.apache.ocean.main.fields.FieldType;
import org.apache.ocean.main.fields.SchemaField;
import org.apache.ocean.main.util.CElement;
import org.apache.ocean.main.util.Constants;
import org.apache.ocean.main.util.NamedList;
import org.apache.ocean.main.util.XMLUtil;
import org.jdom.Element;

public class IndexDocuments extends ArrayList<IndexDocuments.IndexDocument> {
	public IndexDocuments() {
	}

	public IndexDocuments(int size) {
		super(size);
	}

	public IndexDocuments(IndexDocuments indexDocuments) {
		super(indexDocuments);
	}

	public static class IndexDocument extends NamedList<String, Object> implements CElement {
		private IndexSchema.Category indexSchemaCategory;

		public IndexDocument(IndexSchema.Category indexSchemaCategory) {
			this.indexSchemaCategory = indexSchemaCategory;
		}

		public IndexDocument(Element root, IndexSchema.Category indexSchemaCategory) throws ParseException {
			this.indexSchemaCategory = indexSchemaCategory;
			for (Element element : XMLUtil.getChildren(root)) {
				String name = element.getName();
				String text = element.getText();
				SchemaField schemaField = indexSchemaCategory.getField(name);
				FieldType fieldType = schemaField.getFieldType();
				Object value = fieldType.stringToObject(text);
				add(name, value);
			}
		}

		public IndexDocument(Document document, IndexSchema.Category indexSchemaCategory) throws ParseException {
			this.indexSchemaCategory = indexSchemaCategory;
			for (Fieldable fieldable : (List<Fieldable>) document.getFields()) {
				String name = fieldable.name();
				SchemaField schemaField = indexSchemaCategory.getField(name);
				FieldType fieldType = schemaField.getFieldType();
				String readable = fieldType.storedToReadable(fieldable);
				Object value = fieldType.stringToObject(readable);
				add(name, value);
			}
		}

		public Element toElement() {
			Element root = new Element("document");
			for (NamedList.Entry<String, Object> entry : getEntries()) {
				String name = entry.key;
				Object value = entry.value;
				SchemaField schemaField = indexSchemaCategory.getField(name);
				FieldType fieldType = schemaField.getFieldType();
				String valueString = fieldType.objectToExternal(value);
				Element fieldElement = new Element(name);
				fieldElement.setAttribute("type", fieldType.getName());
				fieldElement.setText(valueString);
				root.addContent(fieldElement);
			}
			return root;
		}

		public Long getSnapshotID() {
			return (Long) get(Constants.SNAPSHOTID);
		}

		public Long getID() {
			return (Long) get(Constants.ID);
		}

		public void setSchemaVersion(Long schemaVersion) {
			set(Constants.SCHEMAVERSION, schemaVersion);
		}

		public void setSnapshotID(Long snapshotID) {
			set(Constants.SNAPSHOTID, snapshotID);
		}

		public void setID(Long id) {
			set(Constants.ID, id);
		}

		public Document toDocument() {
			Document document = new Document();
			for (NamedList.Entry<String, Object> entry : getEntries()) {
				String name = entry.key;
				Object value = entry.value;
				SchemaField schemaField = indexSchemaCategory.getField(name);
				String indexedValue = schemaField.getFieldType().objectToIndexed(value);
				Fieldable fieldable = schemaField.createField(indexedValue, 1.0f);
				document.add(fieldable);
			}
			return document;
		}
	}
}
